#ifndef prs_FrmTx_H
#define prs_FrmTx_H
        
#include "frm_control_TPanel.h"
#include "prs_Converter.h"
#include "prs_FrmUnlinkControl.h"
             
namespace prs {
                   
///////////////////////////////////////////////////////////////////////////////
struct TxParams;
struct TxTemplate;
///////////////////////////////////////////////////////////////////////////////

struct TxReceiver //: public prs::IReceiver<prs::TMessage_Base>
 :public prs::IReceiver<TMessage_BeforeVisibleFrmRowChildren>
 ,public prs::IReceiver<TMessage_BeforeSetTemplateParam>
 ,public prs::IReceiver<TMessage_AfterSetTemplateParam>
 ,public prs::IReceiver<TMessage_ClickFrmButton>
 ,public prs::IReceiver<TMessage_BeforeKeyboardKey>
 ,public prs::IReceiver<TMessage_AfterKeyboardKey>
 ,public prs::IReceiver<TMessage_BeforeKeyboardChar>
 ,public prs::IReceiver<TMessage_AfterKeyboardChar>
 ,public prs::IReceiver<TMessage_SelectEnter>
 ,public prs::IReceiver<TMessage_MenuCommand>
{
  TNodeRoot &NodeRoot;
  //
  TxReceiver(
    TNodeRoot &NodeRoot_
  ):NodeRoot(NodeRoot_)
  {}
  //virtual void Receive(prs::TMessage_Base &M) {}
  //
  virtual void Receive(TMessage_BeforeVisibleFrmRowChildren&) {}
  virtual void Receive(TMessage_BeforeSetTemplateParam&) {}
  virtual void Receive(TMessage_AfterSetTemplateParam&) {}
  virtual void Receive(TMessage_ClickFrmButton&) {}
  virtual void Receive(TMessage_BeforeKeyboardKey&) {}
  virtual void Receive(TMessage_AfterKeyboardKey&) {}
  virtual void Receive(TMessage_BeforeKeyboardChar&) {}
  virtual void Receive(TMessage_AfterKeyboardChar&) {}
  virtual void Receive(TMessage_SelectEnter&) {}
  virtual void Receive(TMessage_MenuCommand&) {}
};

///////////////////////////////////////////////////////////////////////////////

struct TxStyle
{
  TxStyle() {
    style = NULL;
  }
  TxStyle(
    TxReceiver         *Receiver,
    const svl::TString &StyleId
  ){
    style = TNodeStyle::searchStyleByIdFromChild(&Receiver->NodeRoot,StyleId);
    //style = Receiver->NodeUnit.SearchStyleById(StyleId);
    if (!style) {
      Except(svl::TString() << "TxStyle[!style] " << StyleId);
    }
  }
  //
  //operator TNodeStyle*() { return style;}
  
private:  
  TNodeStyle *style;
  friend TxParams;
  friend TxTemplate;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TxParams
{
  TxParams(TNodeUseTemplate *UseTemplate) {
    useTemplate = UseTemplate;
  }
  TxParams(TNodeUseTemplate &UseTemplate) {
    useTemplate = &UseTemplate;
  }
  
  //---------------------------------------------------------------------------
  
  //
  void SetValue(
    const svl::TString &ParamId, 
    const svl::TString &Value
  );
  void GetValue(
    const svl::TString &ParamId, 
    svl::TString       &OutValue
  );
  //
  void SetValue(
    const svl::TString &ParamId, 
    int                 Value
  );

  //---------------------------------------------------------------------------

  //  
  void SetValue(
    const svl::TString &ParamId, 
    TxStyle            &Value
  );
  //  
  void SetValue(
    const svl::TString &ParamId, 
    TxStyle            *Value
  );
  //  
  void GetValue(
    const svl::TString &ParamId, 
    TxStyle            &OutValue
  );
  
  //---------------------------------------------------------------------------

  //  
  void DeleteValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *Value
  );
  void PostDeleteValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *Value
  );

  //---------------------------------------------------------------------------

  //  
  void SetValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *Value,
    bool EnDeleteValue = true
  );

/******************
  //
  void ReplaceParam(
    const svl::TString    &in_ParamId,
    int                    in_N,
    TNodeUseTemplate *in_Value,
    bool EnDeleteValue = true
  );
*********************/

  //  
  void AddFirstValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *Value,
    bool EnDeleteValue = true
  );
  //  
  void AddLastValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *Value,
    bool EnDeleteValue = true
  );
  //  
  void AddBeforeValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *CurrValue,
    TNodeUseTemplate   *Value,
    bool EnDeleteValue = true
  );
  //  
  void AddAfterValue(
    const svl::TString &ParamId, 
    TNodeUseTemplate   *CurrValue,
    TNodeUseTemplate   *Value,
    bool EnDeleteValue = true
  );

  //---------------------------------------------------------------------------

  //  
  void SetFocusInRecord(
    const svl::TString &ParamId
  );

private:  
  typedef svl::TArrayPtrFix<frm::control::TPanel*,10> TControlsArray;
  //
  TNodeUseTemplateParam *searchParamById(
    const svl::TString &in_ParamId
  );
  //
  TFrmControlsValue *getControlsValue(
    TNodeUseTemplateParam *Param
  );
  //
  frm::control::TPanel *searchNearParentControlFromChild(
    TNode *FromChild
  );
  //
  void searchNearChildrenControlsFromNode(
    TNode *FromNode,
    TControlsArray &ChildrenControls
  );
  //
  void linkChildrenControlsToParentControl_First(
    frm::control::TPanel *ParentControl,
    TControlsArray &ChildrenControls
  );
  //
  void linkChildrenControlsToParentControl_Last(
    frm::control::TPanel *ParentControl,
    TControlsArray &ChildrenControls
  );
  //
  void linkChildrenControlsToParentControl_Before(
    frm::control::TPanel *ParentControl,
    frm::control::TPanel *CurrChildControl,
    TControlsArray &ChildrenControls
  );
  //
  void linkChildrenControlsToParentControl_After(
    frm::control::TPanel *ParentControl,
    frm::control::TPanel *CurrChildControl,
    TControlsArray &ChildrenControls
  );

/****************************
  //
  frm::control::TPanel *changeParentControl(
    frm::control::TPanel *ParentControl
  ){
    frm::control::TFrame *Frame = dynamic_cast<frm::control::TFrame *>(ParentControl);
    if (Frame) {
      return Frame->Client;
    }
    return ParentControl;
  }
************************/  
  
  svl_Except;
  TNodeUseTemplate *useTemplate;
  friend TxTemplate;
};

///////////////////////////////////////////////////////////////////////////////

struct TxTemplate : public TNodeUseTemplate
{
  TxTemplate(
    TxReceiver         *Receiver,
    const svl::TString &DefTemplateId
  );
 ~TxTemplate();

private:  
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TxMenu //: public TNodeMenu
{
  TxMenu(
    TxReceiver			*Receiver,
	const svl::TString  &MenuId,
	bool MainMenu
  );

  void SetTo( frm::control::TWindow &Window_ );
  void Popup ( frm::control::TWindow &Window_, int x, int y );

  TNodeMenu *Menu;
  
private:
  svl_Except;
};


///////////////////////////////////////////////////////////////////////////////

struct TxSearch : public TNodeUseTemplate
{
  TxSearch(
    TNodeUseTemplate *UseTemplate
  ){
    useTemplate = UseTemplate;
  }
  //
  TNodeUseTemplate *SearchNearParent() {
    return searchNearParent(useTemplate,useTemplate);
  }
  
  void GetSelectionText( svl::TString &str );
private:
  static TNodeUseTemplate *searchNearParent(
    TNodeUseTemplate *FromChild,
    TNodeUseTemplate *Type
  );
  TNodeFrmFrame *searchFrame( prs::TNode *parent );
  TNodeUseTemplate *useTemplate;
};

///////////////////////////////////////////////////////////////////////////////

struct TxWindow : public frm::control::TWindow
{
  TxWindow(
    TNodeRoot        &NodeRoot,
    TNodeUseTemplate &Template
  )
  {
/********  
    tmpl = Template.NewCopy();

    tmpl->Sender = NULL;
    tmpl->Receiver = NULL;

    tmpl->SetParent(&NodeUnit);
    tmpl->Accept(prs::TFrmBuildControl(&Client));
**********/
    Template.SetParent(&NodeRoot.Units.Array.Get(0));//&NodeUnit);
    Template.Accept(prs::TFrmBuildControl(&Client));
    
  }
  //
 ~TxWindow() {
    Client.DeleteChildren();
    //delete tmpl;
  }

private:
  TxTemplate *tmpl;
};

///////////////////////////////////////////////////////////////////////////////
}

#endif
